package org.realogic.cfm.persistence.jdbc;

import java.sql.SQLException;
import java.util.List;

import org.realogic.cfm.domain.KPageResult;
import org.realogic.cfm.persistence.KDataSourceRepository;
import org.realogic.cfm.persistence.KParameter;
import org.realogic.cfm.persistence.dialect.Dialect;
import org.realogic.cfm.persistence.query.QueryCondition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.ConnectionCallback;
import org.springframework.jdbc.core.JdbcTemplate;

public abstract class KJdbcDao {

	private KDataSourceRepository dataSourceRepository;

	public KDataSourceRepository getDataSourceRepository() {
		return dataSourceRepository;
	}

	@Autowired
	@Qualifier("cfm.dataSourceRepository")
	public void setDataSourceRepository(KDataSourceRepository dataSourceRepository) {
		this.dataSourceRepository = dataSourceRepository;
	}

	/**
	 * 获取JdbcTemplate对象
	 * 
	 * @param aDataSourcName
	 *            数据源名称
	 * @return
	 */
	public JdbcTemplate getJdbcTemplate(String aDataSourcName) {
		String temp = aDataSourcName;
		if (temp == null || "".equals(aDataSourcName)) {
			temp = dataSourceRepository.getDefaultDataSourceName();
		}
		JdbcTemplate tmpJdbcTemplate = dataSourceRepository.getJdbcTemplateMap().get(temp);
		if (tmpJdbcTemplate == null) {
			tmpJdbcTemplate = dataSourceRepository.getDefaultJdbcTemplate();
		}
		return tmpJdbcTemplate;
	}

	/**
	 * 获取默认的JdbcTemplate对象
	 * 
	 * @return
	 */
	public JdbcTemplate getJdbcTemplate() {
		return getJdbcTemplate(null);
	}
	
	public String findAsString(final String theSQL, final KParameter... theParams)  {
		JdbcTemplate jdbcTemplate = getJdbcTemplate();
		String s = jdbcTemplate.execute(new ConnectionCallback<String>() {
			public String doInConnection(final java.sql.Connection conn) throws SQLException, DataAccessException {
				return KJdbcDAOUtil.findAsString(conn, theSQL, theParams);
			}
		});
		return s;
	}

	public <T> List<T> findAsList(final String theSQL, final KRowGetter<T> theRsGetter, final List<KParameter> theParams) {
		JdbcTemplate jdbcTemplate = getJdbcTemplate();
		List<T> tmp = jdbcTemplate.execute(new ConnectionCallback<List<T>>() {
			public List<T> doInConnection(final java.sql.Connection conn) throws SQLException, DataAccessException {
				return KJdbcDAOUtil.findAsList(conn, theSQL, theRsGetter, theParams);
			}
		});
		return tmp;
	}

	public <T> int singleExecute(final String theSQL, final T theModel, final KRowSetter<T> theStmtSetter)  {
		JdbcTemplate jdbcTemplate = getJdbcTemplate();
		int tmp = jdbcTemplate.execute(new ConnectionCallback<Integer>() {
			public Integer doInConnection(final java.sql.Connection conn) throws SQLException, DataAccessException {
				return KJdbcDAOUtil.singleExecute(conn, theSQL, theModel, theStmtSetter);
			}
		});
		return tmp;
	}

	public int singleExecute(final String theSQL, final KParameter... theParams) throws DataAccessException {
		JdbcTemplate jdbcTemplate = getJdbcTemplate();
		int tmp = jdbcTemplate.execute(new ConnectionCallback<Integer>() {
			public Integer doInConnection(final java.sql.Connection conn) throws SQLException, DataAccessException {
				return KJdbcDAOUtil.singleExecute(conn, theSQL, theParams);
			}
		});
		return tmp;
	}

	public int singleExecute(final String theSQL, final List<KParameter> theParams) throws DataAccessException {
		JdbcTemplate jdbcTemplate = getJdbcTemplate();
		int tmp = jdbcTemplate.execute(new ConnectionCallback<Integer>() {
			public Integer doInConnection(final java.sql.Connection conn) throws SQLException, DataAccessException {
				return KJdbcDAOUtil.singleExecute(conn, theSQL, theParams);
			}
		});
		return tmp;
	}

	public <T> void batchExecute(final String theSQL, final List<T> theModelList, final KRowSetter<T> theStmtSetter) throws DataAccessException {
		JdbcTemplate jdbcTemplate = getJdbcTemplate();
		jdbcTemplate.execute(new ConnectionCallback<int[]>() {
			public int[] doInConnection(final java.sql.Connection conn) throws SQLException, DataAccessException {
				return KJdbcDAOUtil.batchExecute(conn, theSQL, theModelList, theStmtSetter);
			}
		});
	}

	public <T> KPageResult<T> query(final Dialect dialect, final String theSQL, final QueryCondition theCondition, final KRowGetter<T> theRsGetter) throws DataAccessException {
		JdbcTemplate jdbcTemplate = getJdbcTemplate();
		return jdbcTemplate.execute(new ConnectionCallback<KPageResult<T>>() {
			public KPageResult<T> doInConnection(final java.sql.Connection conn) throws SQLException, DataAccessException {
				return KJdbcDAOUtil.query(dialect, conn, theSQL, theRsGetter,theCondition);
			}
		});
	}

}
